#!/bin/sh
#
# osqueryd 	Start/Stop the osquery daemon.
#
# chkconfig: 345 90 60
# Description:
#  With osquery, you can use SQL to query low-level
#  operating system information. Under the hood, instead
#  of querying static tables, these queries dynamically execute
#  high-performance native code. The results of the
#  SQL query are transparently returned to you quickly and easily
#
### BEGIN INIT INFO
# Provides: osquery osqueryd
# Required-Start: $local_fs $syslog
# Required-Stop: $local_fs $syslog
# Default-Start:  3 4 5
# Default-Stop: 0 1 6
# Short-Description: run osqueryd daemon
# Description:
#   With osquery, you can use SQL to query low-level
#   operating system information. Under the hood, instead
#   of querying static tables, these queries dynamically execute
#   high-performance native code. The results of the
#   SQL query are transparently returned to you quickly and easily
#
#
### END INIT INFO

if [ -z $RETVAL ]; then RETVAL=0; fi
if [ -z $PROG ]; then PROG="osqueryd"; fi
if [ -z $EXEC ]; then EXEC=/opt/osquery/bin/osqueryd; fi
if [ -z $FLAGS_PATH ]; then FLAGS_PATH=/etc/osquery/osquery.flags; fi
if [ -z $REAL_CONFIG_PATH ]; then REAL_CONFIG_PATH=/etc/osquery/osquery.conf; fi
if [ -z $LOCKFILE ]; then LOCKFILE=/var/lock/osqueryd; fi
if [ -z $PIDFILE ]; then PIDFILE=/var/run/osqueryd.pidfile; fi
if [ -z $OLD_PIDFILE ]; then OLD_PIDFILE=/var/run/osqueryd.pid; fi
if [ -z $UID ]; then UID=$(id -u); fi

if [ $UID -eq 0 ] && [ -e /etc/sysconfig/$PROG ]; then
  . /etc/sysconfig/$PROG
fi

if [ -e /etc/init.d/functions ]; then
  . /etc/init.d/functions
fi

if [ ! -e $FLAGS_PATH ] && [ ! -e $REAL_CONFIG_PATH ]; then
  echo "No config file found at $REAL_CONFIG_PATH"
  echo "Additionally, no flags file or config override found at $FLAGS_PATH"
  echo "See '/opt/osquery/share/osquery/osquery.example.conf' for an example config."
  RETVAL=1
fi

move_pidfile() {
  if [ -f $OLD_PIDFILE ]; then
    # Support for deprecated pidfile location.
    mv $OLD_PIDFILE $PIDFILE
  fi
}

ensure_root() {
  if [ $UID -ne 0 ] ; then
    echo "User has insufficient privilege."
    RETVAL=1
  fi
}

start() {
  ensure_root
  move_pidfile

  ARGS=""
  if [ -f $PIDFILE ]; then
    PID=$(cat $PIDFILE)
    PROCNAME=$(ps -p $PID -o comm\=)
    if [ "$PROCNAME" = "$PROG" ]; then
      return 0
    else
      # osqueryd pidfile exists but it's not running
      rm $PIDFILE
    fi
  fi

  if [ -e $FLAGS_PATH ]; then ARGS="$ARGS --flagfile=$FLAGS_PATH"; fi
  if [ -e $REAL_CONFIG_PATH ]; then ARGS="$ARGS --config_path=$REAL_CONFIG_PATH"; fi

  $EXEC $ARGS \
        --pidfile=$PIDFILE \
        --daemonize=true
  RETVAL=$?
}

stop() {
  ensure_root
  move_pidfile

  if [ ! -f $PIDFILE ] ; then
    RETVAL=0
  else
    PID=$(cat $PIDFILE)
    # Terminate the daemon and watchers
    pkill -g $PID
    # Allow the event threads to tear down
    ( while kill -0 $PID >/dev/null 2>&1; do sleep 0.2; done ) & DPID=$!
    # If the event threads are still running after 5 seconds, kill them
    ( sleep 5 && pkill -9 -g $PID && kill -9 $DPID ) 2>/dev/null & WPID=$!
    if wait $DPID 2>/dev/null; then
      pkill -9 -P $WPID
      wait $WPID
    fi
    rm -f $PIDFILE
  fi
}

restart() {
  stop
  start
}

status() {
  if [ -f $PIDFILE ]; then
    PID=$(cat $PIDFILE)
    PROCNAME=$(ps -p $PID -o comm\=)
    if [ "$PROCNAME" = "$PROG" ]; then
      echo "$PROG is already running: $PID"
      RETVAL=0
    else
      # osqueryd pidfile exists but it's not running
      echo "$PROG is not running but a stale pidfile was found."
      RETVAL=7
    fi
  elif [ -f $OLD_PIDFILE ]; then
    PID=$(cat $OLD_PIDFILE)
    PROCNAME=$(ps -p $PID -o comm\=)
    if [ "$PROCNAME" = "$PROG" ]; then
      echo "$PROG is already running (old pidfile): $PID"
      RETVAL=0
    else
      # osqueryd pidfile exists but it's not running
      echo "$PROG is not running but a stale old pidfile was found."
      RETVAL=7
    fi
  else
    echo "$PROG is not running. no pidfile found."
    RETVAL=7
  fi
}

usage() {
  echo "Usage: $0 {start|stop|status|restart}"
  RETVAL=2
}

case "$1" in
    start) start ;;
    stop) stop ;;
    restart) restart ;;
    status) status ;;
    *) usage ;;
esac

exit ${RETVAL}
